package com.example.pulseanalyse.veinPoint;

import android.graphics.Point;
import android.util.Log;

import com.example.pulseanalyse.ConstantCls;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

/**
 * @author: yyw
 * time: 2020/12/2 14:21
 * desc:前端本地分析算法实现
 */
public class myClassPluseAnalysisSD{
    public void setPixelsPerSecond50(){
        pixelsPerSecond=ConstantCls.pixelsPerSecond50;
    }
    public static final double beishu = ConstantCls.beishu;//脉高的标准值约束
//    public static final double pixelsPerSecond = ConstantCls.pixelsPerSecond;//每秒传输的点数
    public static  double pixelsPerSecond = ConstantCls.pixelsPerSecond128;//每秒传输的点数
    private static final String TAG = "myClassPluseAnalysisSD";
    /************** #region 常量 **************/
    public List<Integer> listCopy=new ArrayList<>();//yyw点集合copy
    public int CBFIndexCopy;//yyw主波峰下标拷贝

    /// 主波峰
    public int CBFIndex = 0;

    /// 主波峰起点数组
    public List<Integer> listCBFStart = new ArrayList<>();

    /// 潮波起点
    public int BBFIndex = 0;

    /// 重搏波点
    public int CBGIndex = 0;

    /// 重搏波起点
    public int CBGStartIndex = 0;

    /// 最佳波形的起点
    public int myAutoStartIndex = 0;

    /// 最佳波形的终点
    public int myAutoEndIndex = 0;


    /// 存放新点,疯狂滤波，为了得到准确脉率
    public List<Integer> testList = new ArrayList<>();

    /// 存放新的波峰,疯狂滤波，为了得到准确脉率
    public List<Integer> testCBFList = new ArrayList<>();

    /************** #endregion **************/

    /************** #region 需要提取的脉象参数 **************/

    public double pMax周期 = 0.0;
    public double pMin周期 = 10000.0;

    public boolean p是否间歇 = false;
    public boolean p间歇是否规律 = false;


    public double p周期 = 0.0;
    public double p主波上升期 = 0.0;
    public double p心率 = 0.0;
    public double p主波上部周期 = 0.0;
    public double p主波最大间隔 = 0.0;


    public double p主波幅高 = 0.0;
    public double p主波入射角 = 0.0;
    public double p主波夹角 = 0.0;

    public double p潮波幅高 = 0.0;
    public double 降中峡h4 = 0.0;
    public double 重搏波与降中峡之差h5 = 0.0;


    public double p周期方差 = 0.0;
    public double p脉力方差 = 0.0;


    public double p潮波周期 = 0.0;
    public double p重搏波周期 = 0.0;
    /// h3/h1比值
    public double h3h1 = 0.0;
    /// h4/h1比值
    public double h4h1 = 0.0;
    /// h5/h1比值
    public double h5h1 = 0.0;

    /// 起点到h4对应的横坐标距离
    public double t4 = 0.0;
    /// h4到下一个起点对应的横坐标距离
    public double t5 = 0.0;

    public List<Integer> intList = new ArrayList<>();
    /// 用来存储归一化之后的点列
    public List<Integer> newDataList = new ArrayList<>();
    List<Integer> newDataListCopy = new ArrayList<>();

    /// 上升角数组
    public List<Point> _aListα = new ArrayList<>();
    public List<Point> _bListα = new ArrayList<>();
    public List<Point> _cListα = new ArrayList<>();

    /// 主波夹角数组
    public List<Point> _aListθ = new ArrayList<>();
    public List<Point> _bListθ = new ArrayList<>();
    public List<Point> _cListθ = new ArrayList<>();

    /// 存放单峰数组
    public List<Integer> 单峰List = new ArrayList<>();
    /// 存放双峰波峰数组
    public List<Integer> 双峰List = new ArrayList<>();
    /// 存放三峰及多峰数组
    public List<Integer> 多峰List = new ArrayList<>();

    /************** #endregion **************/

    public myClassPluseAnalysisSD() {
    }

    /**
     * 构造函数，手动分析时调用
     *
     * @param pulseData  数据点列
     * @param startIndex 一个周期的起点
     * @param endIndex   一个周期的终点
     * @param CBFIndex   主波峰
     */
    public myClassPluseAnalysisSD(List<Integer> pulseData, int startIndex, int endIndex, int CBFIndex) {
        try {
            listCopy.addAll(pulseData);//原始数据存储
            CBFIndexCopy=CBFIndex;
            DateGuiyi(pulseData);
            mainAnalyze(startIndex, endIndex, CBFIndex);
            myAutoStartIndex = startIndex;   //最佳脉图的起点
            myAutoEndIndex = endIndex;       //最佳脉图的终点
        }catch (Exception e){
            Log.d(TAG,"======"+e.getMessage());
        }
    }

    /**
     * 算法分析方法
     *
     * @param _startIndex 起点
     * @param _endIndex   终点
     * @param _cbfIndex   主波峰
     */
    public void mainAnalyze(int _startIndex, int _endIndex, int _cbfIndex) {
        /************** #region **************/
        CBFIndex = _cbfIndex;
        listCBFStart.add(_startIndex);  //一个周期的起点和终点分别添加到数组内，以后所有分析只有这两个
        listCBFStart.add(_endIndex);

        for (int i = 0; i < listCBFStart.size(); i++) {
            if (listCBFStart.get(i) > 0) {
                listCBFStart.set(i, checkIsMin(listCBFStart.get(i), 10, newDataList));
            }
        }
        /************** #endregion **************/

        /************** #region 潮波、重搏波、降中峡 在波峰和下一个波峰起点中找 **************/

        int _index01 = -1;
        List<Integer> _intIndexList01 = new ArrayList<>();  //临时存放小波峰拐点
        List<Integer> _intIndexList02 = new ArrayList<>();  //临时存放小波谷拐点

        for (int i = CBFIndex + 15; i < listCBFStart.get(1) - 15; i++) {
            if ((newDataList.get(i) - newDataList.get(i - 2) < 0) && (newDataList.get(i + 2) - newDataList.get(i) >= 0))  //判断波谷拐点
            {
                _intIndexList02.add(i);
                i = i + 4;
            } else if ((newDataList.get(i) - newDataList.get(i - 2) >= 0) && (newDataList.get(i + 2) - newDataList.get(i) < 0))  //判断波峰的拐点
            {
                _intIndexList01.add(i);
                i = i + 4;
                _index01++;
            }
        }
        if (_intIndexList01.size() == 1 && _intIndexList02.size() == 1)   //在波峰和下一个波峰起点之间，如果只有一个小波峰，那么这个小波峰为重搏波，小波谷为降中峡，没有潮波,潮波波峰=主波波峰
        {
            if (_intIndexList01.get(0) > _intIndexList02.get(0)) {
                CBGIndex = _intIndexList01.get(0);
                CBGStartIndex = _intIndexList02.get(0);
                BBFIndex = CBFIndex;
                双峰List.add(0);
            } else {
                单峰List.add(0);
            }
        } else if (_intIndexList01.size() == 2 && _intIndexList02.size() == 2) //在波峰和下一个波峰起点之间，如果有两个小波峰，那么第一个小波峰为潮波，第二个小波峰为重搏波，第二个小波谷为降中峡，
        {
            for (int j = 0; j < _intIndexList01.size(); j++) {
                CBGIndex = Collections.max(_intIndexList01);
                BBFIndex = Collections.min(_intIndexList01);
                break;
            }
            if (Collections.max(_intIndexList02) < Collections.max(_intIndexList01)) {
                CBGStartIndex = Collections.max(_intIndexList02);
            }

            多峰List.add(0);
        } else if (_intIndexList01.size() >= 3 && _intIndexList02.size() == _intIndexList01.size())  //如果有超过三个小波峰，第一个为潮波，其余的波峰进行判断，波幅较大，x轴较长的为重搏波，对应的为降中峡
        {
            BBFIndex = Collections.min(_intIndexList01);
            List<Integer> _intList = new ArrayList<>();
            for (int j = 1; j < _intIndexList01.size(); j++) {
                int _chaZhi = newDataList.get(_intIndexList01.get(j)) - newDataList.get(_intIndexList02.get(j));
                _intList.add(_chaZhi);
            }
            int _index = _intList.indexOf(Collections.max(_intList)) + 1; //其余小波峰与小波谷之差最大的index
            if (_intIndexList01.get(_index) - _intIndexList02.get(_index) > 3) //x轴不能太小
            {
                CBGIndex = _intIndexList01.get(_index);
                CBGStartIndex = _intIndexList02.get(_index);
                多峰List.add(0);
            } else {

            }
        } else if (_intIndexList01.size() == 0 && _intIndexList02.size() == 0) //如果没有拐点的话，判断斜率最小的点，该点先默认为h4  h3==h1 ,,,这样判断的话说明这段波只有两个波峰， 两个波峰的是弦脉或滑脉
        {
            List<Integer> _intIndexMin01 = new ArrayList<>(); // 从主波峰到下一个波峰起点之间找到斜率最小的一点 此点是存差值
            List<Integer> _intIndexMin02 = new ArrayList<>();  // 从主波峰到下一个波峰起点之间找到斜率最小的一点 此点是存差值对应的index

            BBFIndex = CBFIndex;

            for (int i = CBFIndex + 15; i < listCBFStart.get(1) - 15; i += 2) {
                /************** #region 从主波峰到下一个波峰起点之间找到斜率最小的一点 **************/
                int _minIndex = newDataList.get(i) - newDataList.get(i + 1);
                _intIndexMin01.add(_minIndex);
                _intIndexMin02.add(i);
                /************** #endregion **************/
            }
            int _indexMin = 0;
            if (_intIndexMin01.size() > 0) {
                for (int j = 2; j < _intIndexMin01.size() - 1; j++) {
                    if (_intIndexMin01.get(j) - _intIndexMin01.get(j + 1) >= 0) {
                        _indexMin = j + 4;
                        break;
                    }
                }
            }
            if (_indexMin != 0 && _intIndexMin02.size() > 4) {
                if (_indexMin < _intIndexMin02.size()) {
                    CBGStartIndex = (_intIndexMin02.get(_indexMin));
                }
            }
            单峰List.add(0);
        } else if ((_intIndexList01.size() != _intIndexList02.size()) && (_intIndexList01.size() != 0 || _intIndexList02.size() != 0)) //如果波峰波谷不相等的情况下
        {
            if (_intIndexList02.size() > 0) {
                CBGStartIndex = _intIndexList02.get(0);  //以第一个点作为降中峡 ，，只适合单峰或者双峰
                if (_intIndexList01.size() > 0) {
                    for (int j = 0; j < _intIndexList01.size(); j++) {
                        CBGIndex = _intIndexList01.get(_intIndexList01.size() - 1);
                        break;
                    }
                    双峰List.add(0);
                } else {
                    单峰List.add(0);
                }
            } else {
                CBGStartIndex = _intIndexList01.get(0);  //以第一个点作为降中峡 ，，只适合单峰或者双峰
            }
        }
        /************** #endregion **************/

        /************** #region 判断参数 h1 h3 h4 p周期 p心率 p主波上部周期 p主波入射角 p主波夹角 **************/
        p主波幅高 = 0.0;
        p潮波幅高 = 0.0;
        降中峡h4 = 0.0;
        重搏波与降中峡之差h5 = 0.0;
        p周期 = 0.0;
        p心率 = 0.0;
        p主波上部周期 = 0.0; /// 上升1/3宽度
        p主波入射角 = 0.0;
        p主波夹角 = 0.0;
        int pointCenter = (int) Math.ceil((double) (CBFIndex - listCBFStart.get(0)) / 2);

        /************** #region 计算h1 **************/
        int _sumInex = (newDataList.get(CBFIndex) - newDataList.get(listCBFStart.get(0)));
        Log.d(TAG, "主波幅原始数据：" + _sumInex);
        p主波幅高 = _sumInex / beishu;
        /************** #endregion **************/

        /************** #region 计算h3 **************/
        int _chaoboAve = newDataList.get(BBFIndex) - newDataList.get(listCBFStart.get(0));
        if (_chaoboAve != 0) {
            p潮波幅高 = _chaoboAve / beishu;
            if (p潮波幅高 > p主波幅高) {
                p潮波幅高 = p主波幅高;
            }
        } else {
            p潮波幅高 = p主波幅高;
        }
        /************** #endregion **************/

        /************** #region 计算h4 **************/
        int _jzxAve = newDataList.get(CBGStartIndex) - newDataList.get(listCBFStart.get(0));
        if (_jzxAve != 0) {
            降中峡h4 = _jzxAve / beishu;
        } else {
            降中峡h4 = 0;
        }
        /************** #endregion **************/

        /************** #region 计算h5 **************/
        int _cbbAve = newDataList.get(CBGIndex) - newDataList.get(CBGStartIndex);
        if (_cbbAve != 0) {
            重搏波与降中峡之差h5 = _cbbAve / beishu;
        } else {
            重搏波与降中峡之差h5 = 0;
        }
        /************** #endregion **************/

        /************** #region h3/h1 h4/h1 h5/h1 **************/
        if (p主波幅高 != 0.0) {
            h3h1 = p潮波幅高 / p主波幅高;

            h4h1 = 降中峡h4 / p主波幅高;

            h5h1 = 重搏波与降中峡之差h5 / p主波幅高;
        }
        /************** #endregion **************/

        /************** #region 计算p周期 **************/
        p周期 = (double) (listCBFStart.get(1) - listCBFStart.get(0)) / pixelsPerSecond;
        ;
        /************** #endregion **************/

        /************** #region 计算心率 **************/
        p心率 = 60.0 / p周期;
        /**************  #endregion **************/

        /************** #region p主波最大间隔 10.15 **************/

        /************** #endregion **************/

        /************** #region 上升1/3 周期 **************/
        boolean _isExistTop = false;
        boolean _isExistBottom = false;
        int _topIndex = 0;    //上1/3点
        int _bottomIndex = 0; //下1/3点

        double _allHei = newDataList.get(CBFIndex) - newDataList.get(listCBFStart.get(0));
        double _topHei = newDataList.get(CBFIndex) - _allHei / 3;
        for (int i = listCBFStart.get(0) + 5; i < CBFIndex - 5; i++)   //找到上1/3点
        {
            if ((newDataList.get(i - 1) - _topHei < 0) && (newDataList.get(i + 1) - _topHei > 0)) {
                _topIndex = i;
                _isExistTop = true;
                break;
            }
        }
        if (!_isExistTop) {
            if (listCBFStart.get(0) > 0 && CBFIndex > 0 && CBFIndex - listCBFStart.get(0) > 0) {
                int _top = (CBFIndex - listCBFStart.get(0)) * 2 / 3;
                _topIndex = listCBFStart.get(0) + _top;
            }
        }

        for (int i = CBFIndex + 5; i < listCBFStart.get(1) - 5; i++)   //找到下1/3点
        {
            if ((newDataList.get(i - 1) - _topHei > 0) && (newDataList.get(i + 1) - _topHei < 0)) {
                _bottomIndex = i;
                _isExistBottom = true;
                break;
            }
        }

        if (!_isExistBottom) {
            List<Integer> _subList = new ArrayList<>();
            for (int j = CBFIndex; j < listCBFStart.get(1); j++)   //找到下1/3点
            {
                _subList.add(Math.abs((int) (newDataList.get(j) - _topHei)));
            }

            int indexMin = _subList.indexOf(Collections.min(_subList));
            _bottomIndex = CBFIndex + indexMin;
        }

        if (_topIndex != 0 && _bottomIndex != 0) {
            p主波上部周期 = (_bottomIndex - _topIndex) / pixelsPerSecond;
        } else {
            p主波上部周期 = 0;
        }


        /************** #endregion **************/

        /************** #region p主波入射角 三个点 两个波峰起点 +1 / 3 处点 **************/
        try {
            _aListα.clear();
            _bListα.clear();
            _cListα.clear();
            List<Double> angleList1 = new ArrayList<>();
            // int pointCenter = (Int32)Math.Ceiling((Double)(CBFIndex - listCBFStart[0]) / 2);

            _aListα.add(new Point(CBFIndex - (pointCenter + 2), newDataList.get(CBFIndex - (pointCenter + 2))));
            _bListα.add(new Point(CBFIndex - pointCenter, newDataList.get(CBFIndex - pointCenter)));
            _cListα.add(new Point(listCBFStart.get(1), newDataList.get(CBFIndex - (pointCenter + 2)))); //第三个点纵坐标与a点一致


            _aListα.add(new Point(CBFIndex - (pointCenter), newDataList.get(CBFIndex - (pointCenter))));
            _bListα.add(new Point(CBFIndex - (pointCenter - 2), newDataList.get(CBFIndex - (pointCenter - 2))));
            _cListα.add(new Point(listCBFStart.get(1), newDataList.get(CBFIndex - (pointCenter)))); //第三个点纵坐标与a点一致


            _aListα.add(new Point(CBFIndex - (pointCenter + 4), newDataList.get(CBFIndex - (pointCenter + 4))));
            _bListα.add(new Point(CBFIndex - (pointCenter), newDataList.get(CBFIndex - (pointCenter))));
            _cListα.add(new Point(listCBFStart.get(1), newDataList.get(CBFIndex - (pointCenter + 4)))); //第三个点纵坐标与a点一致


            _aListα.add(new Point(CBFIndex - 8, newDataList.get(CBFIndex - 8)));
            _bListα.add(new Point(CBFIndex - 6, newDataList.get(CBFIndex - 6)));
            _cListα.add(new Point(listCBFStart.get(1), newDataList.get(CBFIndex - 8))); //第三个点纵坐标与a点一致


            angleList1.add(Angle(_aListα.get(0), _bListα.get(0), _cListα.get(0)));
            angleList1.add(Angle(_aListα.get(1), _bListα.get(1), _cListα.get(1)));
            angleList1.add(Angle(_aListα.get(2), _bListα.get(2), _cListα.get(2)));
            angleList1.add(Angle(_aListα.get(3), _bListα.get(3), _cListα.get(3)));

            p主波入射角 = Collections.max(angleList1);

            //_aListα = new Point(listCBFStart[0], newDataList[listCBFStart[0]]);
            //_bListα = new Point(listCBFStart[0] + 10, newDataList[listCBFStart[0] + 10]);
            //_cListα = new Point(listCBFStart[1], newDataList[listCBFStart[0]]);

            //p主波入射角 = Angle(_aListα, _bListα, _cListα);

        } catch (Exception e) {
            Log.d(TAG, "p主波入射角 三个点 两个波峰起点 +1 / 3 处,异常===" + e.getMessage());
        }
        /************** #endregion **************/

        /************** #region p主波夹角 **************/
        try {
            _aListθ.clear();
            _bListθ.clear();
            _cListθ.clear();
            List<Double> angleList2 = new ArrayList<>(); //记录主播夹角的数组
            int pintTop = (int) getPointX(CBFIndex - (pointCenter - 2), newDataList.get(CBFIndex - (pointCenter - 2)), CBFIndex - pointCenter,
                    newDataList.get(CBFIndex - pointCenter), CBFIndex + 5, newDataList.get(CBFIndex + 5),
                    CBFIndex + 7, newDataList.get(CBFIndex + 7));  //利用两条线的交点找到顶点

            int pointBottom = CBFIndex + 20; //下支的点，根据这个点来找夹角

            for (int j = CBFIndex + 2; j < listCBFStart.get(1) - 2; j++) {
                if (newDataList.get(j - 1) > newDataList.get(pointCenter) && newDataList.get(j + 1) < newDataList.get(pointCenter)) {
                    pointBottom = j;
                    break;
                }
            }

            //上升期从中点开始计算，上升期不变，下降期开始遍历,此时的顶点是默认的

            for (int j = CBFIndex + 1; j < pointBottom; j++) {
                _aListθ.add(new Point(CBFIndex - pointCenter, newDataList.get(CBFIndex - pointCenter)));
                _bListθ.add(new Point(CBFIndex, newDataList.get(CBFIndex)));
                _cListθ.add(new Point(j, newDataList.get(j)));
            }

            //下降期不变，遍历上升期
            for (int j = 1; j < pointCenter; j++) {
                _aListθ.add(new Point(CBFIndex - j, newDataList.get(CBFIndex - j)));
                _bListθ.add(new Point(CBFIndex, newDataList.get(CBFIndex)));
                _cListθ.add(new Point(CBFIndex + 10, newDataList.get(CBFIndex + 10)));
            }

            if (pintTop > pointCenter && pintTop < CBFIndex + 10) {
                //上升期从中点开始计算，上升期不变，下降期开始遍历,此时的顶点是交点

                for (int j = pintTop + 1; j < pointBottom; j++) {
                    _aListθ.add(new Point(CBFIndex - pointCenter, newDataList.get(CBFIndex - pointCenter)));
                    _bListθ.add(new Point(pintTop, newDataList.get(pintTop)));
                    _cListθ.add(new Point(j, newDataList.get(j)));
                }

                //下降期不变，遍历上升期
                for (int j = 1; j < pointCenter; j++) {
                    _aListθ.add(new Point(CBFIndex - j, newDataList.get(CBFIndex - j)));
                    _bListθ.add(new Point(pintTop, newDataList.get(pintTop)));
                    _cListθ.add(new Point(CBFIndex + 10, newDataList.get(CBFIndex + 10)));
                }
            }

            for (int j = 0; j < _aListθ.size(); j++) {
                angleList2.add(Angle(_bListθ.get(j), _aListθ.get(j), _cListθ.get(j)));
            }

            Iterator<Double> it = angleList2.iterator();
            while (it.hasNext()) {
                if (Double.isNaN(it.next())) {
                    it.remove();
                }
            }
//            for (int j = 0; j < angleList2.size(); j++) {
//                if (Double.isNaN(angleList2[j])) {
//                    angleList2.RemoveAt(j);
//                }
//            }
            p主波夹角 = Collections.min(angleList2) - 3;

            //_aListθ.Add(new Point(CBFIndex - pointCenter, newDataList[CBFIndex - pointCenter]));
            //_bListθ.Add(new Point(CBFIndex, newDataList[CBFIndex]));
            //_cListθ.Add(new Point(CBFIndex + pointCenter, newDataList[CBFIndex + pointCenter]));

            //_aListθ.Add(new Point(CBFIndex - (pointCenter - 2), newDataList[CBFIndex - (pointCenter - 2)]));
            //_bListθ.Add(new Point(CBFIndex, newDataList[CBFIndex]));
            //_cListθ.Add(new Point(CBFIndex + (pointCenter - 2), newDataList[CBFIndex + (pointCenter - 2)]));

            //_aListθ.Add(new Point(CBFIndex - (pointCenter + 2), newDataList[CBFIndex - (pointCenter + 2)]));
            //_bListθ.Add(new Point(CBFIndex, newDataList[CBFIndex]));
            //_cListθ.Add(new Point(CBFIndex + (pointCenter + 2), newDataList[CBFIndex + (pointCenter + 2)]));

            //double angle1 = Angle(_bListθ[0], _aListθ[0], _cListθ[0]);
            //double angle2 = Angle(_bListθ[1], _aListθ[1], _cListθ[1]);
            //double angle3 = Angle(_bListθ[2], _aListθ[2], _cListθ[2]);

            //p主波夹角 = Math.Min(Math.Min(angle1, angle2), angle3);

        } catch (Exception e) {
            Log.d(TAG, "#region p主波夹角,异常===" + e.getMessage());
        }

        /************** #endregion **************/

        /**************  #region 计算p主波上升期 (t1) **************/
        List<Integer> startXList = new ArrayList<>(); //起始点坐标list

        //  int pointCenter = (Int32)Math.Ceiling((Double)(CBFIndex - listCBFStart[0]) / 2);

        startXList.add((int) getPointX(CBFIndex - (pointCenter + 2), newDataList.get(CBFIndex - (pointCenter + 2)),
                CBFIndex - pointCenter, newDataList.get(CBFIndex - pointCenter),
                listCBFStart.get(0), newDataList.get(listCBFStart.get(0)), listCBFStart.get(1), newDataList.get(listCBFStart.get(0))));  //中心点下面的两个点及中心点

        startXList.add((int) getPointX(CBFIndex - pointCenter, newDataList.get(CBFIndex - pointCenter),
                CBFIndex - (pointCenter - 2), newDataList.get(CBFIndex - (pointCenter - 2)),
                listCBFStart.get(0), newDataList.get(listCBFStart.get(0)), listCBFStart.get(1), newDataList.get(listCBFStart.get(0)))); //中心点上面的两个点及中心点

        startXList.add((int) getPointX(CBFIndex - 5, newDataList.get(CBFIndex - 5),
                CBFIndex - pointCenter, newDataList.get(CBFIndex - pointCenter),
                listCBFStart.get(0), newDataList.get(listCBFStart.get(0)), listCBFStart.get(1), newDataList.get(listCBFStart.get(0)))); //顶点下面5个点及中心点

        int startX = Collections.max(startXList);

        if (startX >= listCBFStart.get(0) && startX <= CBFIndex - 5) {
            p主波上升期 = (double) (CBFIndex - startX) / pixelsPerSecond;
        } else {
            p主波上升期 = (double) (CBFIndex - listCBFStart.get(0)) / pixelsPerSecond;
        }
        /************** #endregion **************/

        /************** #region 计算 p重搏波周期 **************/
        try {
            p重搏波周期 = p周期;
            // Console.WriteLine("t4：" + t4.ToString("0.00"));
        } catch (Exception e) {
            Log.d(TAG, "#region 计算 p重搏波周期,异常===" + e.getMessage());
        }
        /************** #endregion **************/

        /************** #region 计算t5 **************/
        t5 = (listCBFStart.get(1) - CBGIndex) / pixelsPerSecond;
        /************** #endregion**************/

        /************** #region 计算 p潮波周期 **************/
        try {
            p潮波周期 = (BBFIndex - listCBFStart.get(0)) / pixelsPerSecond;
        } catch (Exception e) {
            Log.d(TAG, "#region 计算 p潮波周期,异常===" + e.getMessage());
        }
        /************** #endregion **************/

        /************** #region 计算脉力方差 **************/
        double _fangchaSum = 0;
        _fangchaSum = p主波幅高 - ((newDataList.get(CBFIndex) - newDataList.get(listCBFStart.get(0))) / beishu);
        p脉力方差 = _fangchaSum * _fangchaSum;
        /************** #endregion **************/
    }

    /// 归一化数据
    public void DateGuiyi(List<Integer> pulseData) {
        /************** #region **************/
        // newDataList.Clear();
        //testList.Clear();
        //for (int i = 0; i < pulseData.Count; i++)
        //{
        //    newDataListCopy.Add(pulseData[i]);
        //}
        //double _min1 = newDataListCopy.Min();
        //double _max1 = newDataListCopy.Max();
        //for (int i = 0; i < newDataListCopy.Count; i++)
        //{
        //    double _returnOne = (newDataListCopy[i] - _min1) / (_max1 - _min1);
        //    double _beishu = _returnOne * 250;
        //    int _trueValue = (Int32)_beishu;
        //    newDataList.Add(_trueValue);
        //    testList.Add(_trueValue);  //测试点
        //}

        //for (int i = 0; i < 5; i++)
        //{
        //    newDataList = gaosijunhua(newDataList);
        //}

        //for (int i = 0; i < 18; i++)
        //{
        //    testList = gaosijunhua(testList);
        //}
        /************** #endregion **************/

        newDataList.clear();
        testList.clear();


        for (int i = 0; i < pulseData.size(); i++) {
            newDataList.add(pulseData.get(i));
        }
        double _min1 = Collections.min(newDataList);
        double _max1 = Collections.max(newDataList);
        for (int i = 0; i < newDataList.size(); i++) {
            double _returnOne = (newDataList.get(i) - _min1) / (_max1 - _min1);
            double _beishu = _returnOne * 250;
            int _trueValue = (int) _beishu;
            testList.add(_trueValue);  //测试点
        }

        //for (int i = 0; i < 2; i++)
        //{
        //    newDataList = gaosijunhua(newDataList);
        //}
        for (int i = 0; i < 18; i++) {
            testList = gaosijunhua(testList);
        }

    }

    /************** #region 主函数调用的一些方法，包括均滑、查找一段点列的最大最小值，找角度 **************/

    /// <summary>
    /// 均滑
    /// </summary>
    /// <param name="_list"></param>
    /// <param name="_blockSize"></param>
    /// <returns></returns>
    public List<Integer> gaosijunhua(List<Integer> _list) {
        int _blockSize = 3;
        List<Integer> list1 = new ArrayList<>();
        for (int i = 0; i < _list.size(); i++) {
            list1.add(_list.get(i));
        }

        for (int i = 0; i < _list.size(); i++) {
            int _num = 0;
            int _total = 0;
            for (int i1 = i - _blockSize; i1 <= i + _blockSize; i1++) {
                if (i1 >= 0 && i1 < _list.size()) {
                    _num++;
                    _total += list1.get(i1);
                }
            }
            list1.set(i, _total / _num);
        }
        return list1;
    }

    public int checkIsMax(int _index, int _blockSize, List<Integer> _list) {
        int _returnIndex = _index;
        double _maxV = _list.get(_index);
        for (int i = Math.max(0, _index - _blockSize); i < Math.min(_list.size(), _index + _blockSize); i++) {
            if (_list.get(i) > _maxV) {
                _maxV = _list.get(i);
                _returnIndex = i;
            }
        }
        return _returnIndex;
    }

    public int checkIsMin(int _index, int _blockSize, List<Integer> _list) {
        int _returnIndex = _index;
        double _minV = _list.get(_index);
        for (int i = Math.max(0, _index - _blockSize); i < Math.min(_list.size(), _index + _blockSize); i++) {
            if (_list.get(i) < _minV) {
                _minV = _list.get(i);
                _returnIndex = i;
            }
        }
        return _returnIndex;
    }

    public double Angle(Point cen, Point first, Point second) {
        double M_PI = 3.1415926535897;

        double ma_x = first.x - cen.x;
        double ma_y = first.y - cen.y;
        double mb_x = second.x - cen.x;
        double mb_y = second.y - cen.y;
        double v1 = (ma_x * mb_x) + (ma_y * mb_y);
        double ma_val = Math.sqrt(ma_x * ma_x + ma_y * ma_y);
        double mb_val = Math.sqrt(mb_x * mb_x + mb_y * mb_y);
        double cosM = v1 / (ma_val * mb_val);
        double angleAMB = Math.acos(cosM) * 180 / M_PI;

        return angleAMB;
    }

    /**
     * A的直线方程为l1:y-y1=(y2-y1)(x-x1)/(x2-x1)
     * B的两点为(x3, y3),(x4, y4)
     * 则B的直线方程为l2:y-y3=(y4-y3)(x-x3)/(x4-x3)
     * 联立解出交点坐标为的横坐标为：
     * x=(k2x3-y3-k1x1+y1)/(k2-k1)
     * 其中k1=(y2-y1)/(x2-x1)
     * k2=(y4-y3)/(x4-x3)
     * 可以推导出来
     * x = ((x2 - x1) * (x3 - x4) * (y3 - y1) -
     * x3 * (x2 - x1) * (y3 - y4) + x1 * (y2 - y1) * (x3 - x4))
     * ((y2 - y1) * (x3 - x4) - (x2 - x1) * (y3 - y4));
     *
     * @return 返回两条直线相交的X坐标
     */
    public double getPointX(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) {
        try {
            return ((x2 - x1) * (x3 - x4) * (y3 - y1) -
                    x3 * (x2 - x1) * (y3 - y4) + x1 * (y2 - y1) * (x3 - x4)) /
                    ((y2 - y1) * (x3 - x4) - (x2 - x1) * (y3 - y4));
        } catch (Exception e) {
            Log.d(TAG, "返回两条直线相交的X坐标,异常===" + e.getMessage());
            return 0;
        }

    }
    /************** #endregion **************/
}
